package com.erp.erp_servers.warehouse.imp;

import com.erp.erp_dao.warehouse.IStockDao;
import com.erp.erp_dao.warehouse.IWarehouseRentDao;
import com.erp.erp_entitys.warehouse.entity.StockEntity;
import com.erp.erp_entitys.warehouse.entity.WarehouseRentEntity;
import com.erp.erp_entitys.warehouse.req.RentalFeeInfoReq;
import com.erp.erp_entitys.warehouse.req.RentalFeePageListReq;
import com.erp.erp_servers.warehouse.IWarehouseRentService;
import com.erp.utils.DateUtils;
import com.erp.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * @ClassName : WarehouseRentServiceImp
 * @Description : 海外仓库租金实现类
 * @Author : lst
 * @Date: 2021-06-16 03:04
 */
@Service
public class WarehouseRentServiceImp implements IWarehouseRentService {

    /**
     * 注入仓库租金mapper
     */
    private final IWarehouseRentDao warehouseRentDao;

    /**
     * 注入库存mapper
     */
    private final IStockDao stockDao;

    @Autowired
    public WarehouseRentServiceImp(IWarehouseRentDao warehouseRentDao, IStockDao stockDao) {
        this.warehouseRentDao = warehouseRentDao;
        this.stockDao = stockDao;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public WarehouseRentEntity queryById(Integer id) {
        return warehouseRentDao.queryById(id);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param warehouseRent 实例对象
     * @return 对象列表
     */
    @Override
    public List<WarehouseRentEntity> queryAll(WarehouseRentEntity warehouseRent) {
        return warehouseRentDao.queryAll(warehouseRent);
    }

    /**
     * 新增数据
     *
     * @param warehouseRent 实例对象
     * @return 影响行数
     */
    @Override
    public int insert(WarehouseRentEntity warehouseRent) {
        return warehouseRentDao.insert(warehouseRent);
    }

    /**
     * 修改数据
     *
     * @param warehouseRent 实例对象
     * @return 影响行数
     */
    @Override
    public int update(WarehouseRentEntity warehouseRent) {
        return warehouseRentDao.update(warehouseRent);
    }

    /**
     * 获取海外仓库租金费信息
     * @param req 实例对象
     * @return 海外仓库租金费信息
     */
    @Override
    public List<WarehouseRentEntity> getRentalFeeListByQuery(RentalFeePageListReq req) {
        return warehouseRentDao.getRentalFeeListByQuery(req);
    }

    /**
     * 海外仓库租金费计算
     */
    @Override
    public void autoShareRentalFee() {
        //初始化查询对象
        RentalFeeInfoReq req = new RentalFeeInfoReq();
        //时间为当前时间
        req.setCurrentDate(DateUtils.format(new Date()));
        //状态为:已启动
        req.setStatus(2);
        //数据有效
        req.setValid(1);
        //调用接口查询结果
        List<WarehouseRentEntity> rentalFeeInfo = warehouseRentDao.getRentalFeeInfo(req);
        if(CollectionUtils.isEmpty(rentalFeeInfo)){
            return;
        }
        for(WarehouseRentEntity rental : rentalFeeInfo){

            //更新剩余金额
            updateBalance(rental);

            //仓库编码
            String warehouseCode = rental.getWarehouseCode();
            if(StringUtils.isEmpty(warehouseCode)){
                continue;
            }
            //获取该仓库对应的库存信息
            List<StockEntity> stockList = stockDao.getStockByWarehouseCode(warehouseCode);
            if(CollectionUtils.isEmpty(stockList)){
                continue;
            }
            //分摊条件(1.净重 2.毛重 3.体积 4.数量)
            Integer sharingConditions = rental.getSharingConditions();
            if(null == sharingConditions){
                continue;
            }
            //每日库存租金
            BigDecimal dailyApportionmentAmount = new BigDecimal("0");
            if(StringUtil.isNotEmpty(rental.getDailyApportionmentAmount())){
                dailyApportionmentAmount = rental.getDailyApportionmentAmount();
            }
            switch (sharingConditions){
                case 1 :
                    //净重:分摊条件为净重时,更新海外仓库租金费
                    getNewWarehouseRentalFeeForNetWeight(stockList, dailyApportionmentAmount);
                    break;
                case 2:
                    //毛重:分摊条件为毛重时,更新海外仓库租金费
                    getNewWarehouseRentalFeeForGrossWeight(stockList, dailyApportionmentAmount);
                    break;
                case 3:
                    //体积:分摊条件为体积时,更新海外仓库租金费
                    getNewWarehouseRentalFeeForBulk(stockList, dailyApportionmentAmount);
                    break;
                case 4:
                    //数量:分摊条件为数量时,更新海外仓库租金费
                    getNewWarehouseRentalFeeForQuantity(stockList, dailyApportionmentAmount);
                    break;
            }

        }

    }

    /**
     * 更新剩余金额
     * @param rental 仓库租金实体对象
     */
    private void updateBalance(WarehouseRentEntity rental){
        //剩余金额 = 海外仓库租金总额-(海外仓库租金总额/分摊天数*执行日期与当前日期相差的天数)
        //执行日期与当前日期相差的天数
        int day = 0;
        try {
            day = DateUtils.daysBetween(rental.getExecutionDate(), new Date());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //海外仓库租金总额
        BigDecimal totalRent = rental.getTotalRent();
        //分摊天数
        BigDecimal apportionedDays = new BigDecimal("0");
        if(StringUtil.isNotEmpty(rental.getApportionedDays())){
            apportionedDays = rental.getApportionedDays();
        }
        if(apportionedDays.compareTo(BigDecimal.ZERO) == 0){
            //分摊天数为0,不修改
            return;
        }
        BigDecimal everyNum = totalRent.divide(apportionedDays, 4, BigDecimal.ROUND_HALF_UP);
        //得到最新的剩余金额
        BigDecimal balance = totalRent.subtract((everyNum.multiply(new BigDecimal(Integer.toString(day)))));

        WarehouseRentEntity rentReq = new WarehouseRentEntity();
        rentReq.setId(rental.getId());
        rentReq.setBalance(balance);
        //更新剩余金额
        warehouseRentDao.update(rentReq);
    }

    /**
     * 分摊条件为净重时,更新海外仓库租金费
     * @param stockList 相关仓库的库存信息
     * @param dailyApportionmentAmount 每日库存租金
     */
    private void getNewWarehouseRentalFeeForNetWeight(List<StockEntity> stockList, BigDecimal dailyApportionmentAmount){
        //仓库总净重
        BigDecimal netWeightSum = new BigDecimal("0");
        //第一次循环,获取仓库总净重
        for(StockEntity stock : stockList){
            BigDecimal netWeight = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getNetWeight())){
                netWeight = stock.getNetWeight();
            }
            //净重累加
            netWeightSum = netWeightSum.add(netWeight);
        }
        if(netWeightSum.compareTo(BigDecimal.ZERO) == 0){
            //仓库总净重为0,无意义
            return;
        }
        //第二次循环,重新计算海外仓库租金费
        for(StockEntity stock : stockList){
            //产品净重
            BigDecimal netWeight = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getNetWeight())){
                netWeight = stock.getNetWeight();
            }
            //产品数量
            BigDecimal realQuantity = stock.getRealQuantity();
            if(!StringUtil.isNotEmpty(realQuantity)){
                //产品数量为0,本次不做计算
                continue;
            }
            //历史累计分摊
            BigDecimal warehouseRentalFee = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getWarehouseRentalFee())){
                warehouseRentalFee = stock.getWarehouseRentalFee();
            }
            //[(产品净重/仓库总净重*每日库存租金)/产品数量]+历史累计分摊
            //产品净重/仓库总净重
            BigDecimal stepOne = netWeight.divide(netWeightSum, 6, BigDecimal.ROUND_HALF_UP);
            //stepOne*每日库存租金
            BigDecimal stepTwo = stepOne.multiply(dailyApportionmentAmount);
            //stepTwo/产品数量
            BigDecimal stepThree = stepTwo.divide(realQuantity, 6, BigDecimal.ROUND_HALF_UP);
            //stepThree + 历史累计分摊
            //新的海外仓库租金费
            BigDecimal newWarehouseRentalFee = stepThree.add(warehouseRentalFee);

            //更新海外仓库租金费
            StockEntity updateReq = new StockEntity();
            updateReq.setId(stock.getId());
            updateReq.setWarehouseRentalFee(newWarehouseRentalFee);
            stockDao.update(updateReq);
        }

    }

    /**
     * 分摊条件为毛重时,更新海外仓库租金费
     * @param stockList 相关仓库的库存信息
     * @param dailyApportionmentAmount 每日库存租金
     */
    private void getNewWarehouseRentalFeeForGrossWeight(List<StockEntity> stockList, BigDecimal dailyApportionmentAmount){
        //仓库总毛重
        BigDecimal grossWeightSum = new BigDecimal("0");
        //第一次循环,获取仓库总毛重
        for(StockEntity stock : stockList){
            BigDecimal grossWeight = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getGrossWeight())){
                grossWeight = stock.getGrossWeight();
            }
            //毛重累加
            grossWeightSum = grossWeightSum.add(grossWeight);
        }
        if(grossWeightSum.compareTo(BigDecimal.ZERO) == 0){
            //仓库总毛重为0,无意义
            return;
        }
        //第二次循环,重新计算海外仓库租金费
        for(StockEntity stock : stockList){
            //产品毛重
            BigDecimal grossWeight = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getGrossWeight())){
                grossWeight = stock.getGrossWeight();
            }
            //产品数量
            BigDecimal realQuantity = stock.getRealQuantity();
            if(!StringUtil.isNotEmpty(realQuantity)){
                //产品数量为0,本次不做计算
                continue;
            }
            //历史累计分摊
            BigDecimal warehouseRentalFee = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getWarehouseRentalFee())){
                warehouseRentalFee = stock.getWarehouseRentalFee();
            }
            //[(产品毛重/仓库总毛重*每日库存租金)/产品数量]+历史累计分摊
            //产品毛重/仓库总毛重
            BigDecimal stepOne = grossWeight.divide(grossWeightSum, 6, BigDecimal.ROUND_HALF_UP);
            //stepOne*每日库存租金
            BigDecimal stepTwo = stepOne.multiply(dailyApportionmentAmount);
            //stepTwo/产品数量
            BigDecimal stepThree = stepTwo.divide(realQuantity, 6, BigDecimal.ROUND_HALF_UP);
            //stepThree + 历史累计分摊
            //新的海外仓库租金费
            BigDecimal newWarehouseRentalFee = stepThree.add(warehouseRentalFee);

            //更新海外仓库租金费
            StockEntity updateReq = new StockEntity();
            updateReq.setId(stock.getId());
            updateReq.setWarehouseRentalFee(newWarehouseRentalFee);
            stockDao.update(updateReq);
        }
    }

    /**
     * 分摊条件为体积时,更新海外仓库租金费
     * @param stockList 相关仓库的库存信息
     * @param dailyApportionmentAmount 每日库存租金
     */
    private void getNewWarehouseRentalFeeForBulk(List<StockEntity> stockList, BigDecimal dailyApportionmentAmount){
        //仓库总体积
        BigDecimal bulkSum = new BigDecimal("0");
        //第一次循环,获取仓库总体积
        for(StockEntity stock : stockList){
            BigDecimal bulk = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getBulk())){
                bulk = stock.getBulk();
            }
            //体积累加
            bulkSum = bulkSum.add(bulk);
        }
        if(bulkSum.compareTo(BigDecimal.ZERO) == 0){
            //仓库总体积为0,无意义
            return;
        }
        //第二次循环,重新计算海外仓库租金费
        for(StockEntity stock : stockList){
            //产品体积
            BigDecimal bulk = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getBulk())){
                bulk = stock.getBulk();
            }
            //产品数量
            BigDecimal realQuantity = stock.getRealQuantity();
            if(!StringUtil.isNotEmpty(realQuantity)){
                //产品数量为0,本次不做计算
                continue;
            }
            //历史累计分摊
            BigDecimal warehouseRentalFee = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getWarehouseRentalFee())){
                warehouseRentalFee = stock.getWarehouseRentalFee();
            }
            //[(产品体积/仓库总体积*每日库存租金)/产品数量]+历史累计分摊
            //产品体积/仓库总体积
            BigDecimal stepOne = bulk.divide(bulkSum, 6, BigDecimal.ROUND_HALF_UP);
            //stepOne*每日库存租金
            BigDecimal stepTwo = stepOne.multiply(dailyApportionmentAmount);
            //stepTwo/产品数量
            BigDecimal stepThree = stepTwo.divide(realQuantity, 6, BigDecimal.ROUND_HALF_UP);
            //stepThree + 历史累计分摊
            //新的海外仓库租金费
            BigDecimal newWarehouseRentalFee = stepThree.add(warehouseRentalFee);

            //更新海外仓库租金费
            StockEntity updateReq = new StockEntity();
            updateReq.setId(stock.getId());
            updateReq.setWarehouseRentalFee(newWarehouseRentalFee);
            stockDao.update(updateReq);
        }
    }

    /**
     * 分摊条件为数量时,更新海外仓库租金费
     * @param stockList 相关仓库的库存信息
     * @param dailyApportionmentAmount 每日库存租金
     */
    private void getNewWarehouseRentalFeeForQuantity(List<StockEntity> stockList, BigDecimal dailyApportionmentAmount){
        //仓库总数量
        BigDecimal realQuantitySum = new BigDecimal("0");
        //第一次循环,获取仓库总数量
        for(StockEntity stock : stockList){
            BigDecimal realQuantity = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getRealQuantity())){
                realQuantity = stock.getRealQuantity();
            }
            //数量累加
            realQuantitySum = realQuantitySum.add(realQuantity);
        }
        if(realQuantitySum.compareTo(BigDecimal.ZERO) == 0){
            //仓库总数量为0,无意义
            return;
        }
        //第二次循环,重新计算海外仓库租金费
        for(StockEntity stock : stockList){
            //产品数量
            BigDecimal realQuantity = stock.getRealQuantity();
            if(!StringUtil.isNotEmpty(realQuantity)){
                //产品数量为0,本次不做计算
                continue;
            }
            //历史累计分摊
            BigDecimal warehouseRentalFee = new BigDecimal("0");
            if(StringUtil.isNotEmpty(stock.getWarehouseRentalFee())){
                warehouseRentalFee = stock.getWarehouseRentalFee();
            }
            //[(产品数量/仓库总数量*每日库存租金)/产品数量]+历史累计分摊
            //产品数量/仓库总数量
            BigDecimal stepOne = realQuantity.divide(realQuantitySum, 6, BigDecimal.ROUND_HALF_UP);
            //stepOne*每日库存租金
            BigDecimal stepTwo = stepOne.multiply(dailyApportionmentAmount);
            //stepTwo/产品数量
            BigDecimal stepThree = stepTwo.divide(realQuantity, 6, BigDecimal.ROUND_HALF_UP);
            //stepThree + 历史累计分摊
            //新的海外仓库租金费
            BigDecimal newWarehouseRentalFee = stepThree.add(warehouseRentalFee);

            //更新海外仓库租金费
            StockEntity updateReq = new StockEntity();
            updateReq.setId(stock.getId());
            updateReq.setWarehouseRentalFee(newWarehouseRentalFee);
            stockDao.update(updateReq);
        }
    }

}
